import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ObjectNode;


import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Instant;

import java.util.Base64;
import java.util.UUID;


/**
 * @Description: 对接coze生成jwt
 * @Author: limeng
 * @Date: 2025/1/14
 */

public class CozeAuth {


    // 使用统一的 Base64Url 编码方法

    private static String base64UrlEncode(byte[] data) {

        return Base64.getUrlEncoder().withoutPadding().encodeToString(data);

    }

    // 生成 JWT Token

    public static String generateJwt(String privateKeyPath, String kid, String iss, String aud) throws Exception {

        // 1. 定义并编码 Header

        ObjectMapper objectMapper = new ObjectMapper();

        objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);

        ObjectNode headerNode = objectMapper.createObjectNode();

        headerNode.put("alg", "RS256");  // 固定为 RS256

        headerNode.put("typ", "JWT");    // 固定为 JWT

        headerNode.put("kid", kid);      // OAuth 应用的公钥指纹

        String headerJson = objectMapper.writeValueAsString(headerNode);

        String headerEncoded = base64UrlEncode(headerJson.getBytes(StandardCharsets.UTF_8));

        // 2. 定义并编码 Payload

        String jti = UUID.randomUUID().toString().replace("-", "");  // 随机生成 jti

        long now = Instant.now().getEpochSecond();  // 当前时间（UTC）

        // JWT 开始生效的时间，秒级时间戳

        long exp = now + 3600;  // 过期时间，设置为1小时

        ObjectNode payloadNode = objectMapper.createObjectNode();

        payloadNode.put("iss", iss);  // OAuth 应用的 ID

        payloadNode.put("aud", aud);  // 扣子 API 的 Endpoint

        payloadNode.put("iat", now);  // 开始生效的时间

        payloadNode.put("exp", exp);  // 过期时间

        payloadNode.put("jti", jti);  // 随机字符串，防止重放攻击
        payloadNode.put("session_name","lisi");

        String payloadJson = objectMapper.writeValueAsString(payloadNode);

        String payloadEncoded = base64UrlEncode(payloadJson.getBytes(StandardCharsets.UTF_8));

        // 3. 生成 Signature

        // 拼接 header 和 payload

        String message = headerEncoded + "." + payloadEncoded;

        // 加载私钥文件

        PrivateKey privateKey = loadPrivateKey(privateKeyPath);

        // 使用私钥签名

        Signature signature = Signature.getInstance("SHA256withRSA");

        signature.initSign(privateKey);

        signature.update(message.getBytes(StandardCharsets.UTF_8));

        byte[] signatureBytes = signature.sign();

        // 将签名进行 Base64Url 编码

        String signatureEncoded = base64UrlEncode(signatureBytes);

        // 4. 拼接 JWT

        return headerEncoded + "." + payloadEncoded + "." + signatureEncoded;

    }

    // 加载私钥方法

    private static PrivateKey loadPrivateKey(String privateKeyPath) throws Exception {

        File keyFile = new File(privateKeyPath);// ignore_security_alert

        byte[] keyBytes;

        try {

            keyBytes = Files.readAllBytes(keyFile.toPath());

        } catch (IOException e) {


            throw e;

        }

        String privateKeyPEM = new String(keyBytes, StandardCharsets.UTF_8);

        privateKeyPEM = privateKeyPEM.replace("-----BEGIN PRIVATE KEY-----", "")

                .replace("-----END PRIVATE KEY-----", "")

                .replaceAll("\\s+", "");  // 移除PEM格式的标头和换行

        byte[] decodedKey = Base64.getDecoder().decode(privateKeyPEM);

        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);

        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        return keyFactory.generatePrivate(keySpec);

    }

    public static void main(String[] args) throws Exception {
            String privateKeyPath = "D:\\private-projects\\springboot\\java-demo\\src\\main\\java\\private_key.pem";  // 替换为你的私钥路径

            String kid = "Ecc_6ziX8guXabDIpklROSA07gAFD2bdEZgtKDAGAFw";  // 替换为实际公钥指纹

            String iss = "1194673259667";  // 替换为实际 OAuth 应用 ID

            String aud = "api.coze.cn";  // 替换为实际 API Endpoint

            String jwtToken = generateJwt(privateKeyPath, kid, iss, aud);

            System.out.println(jwtToken);
    }

}

